/*
    实现一个函数让进程（服务）变成守护进程，如果当前进程执行了这个函数，那么当前进程就成守护进程
*/
#include <cstdlib>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>

const char* defaultDir = "/";
const char* dev_null = "/dev/null";
void daemon(bool isChdir, bool isClose)
{
    /*
    isChdir: 是否改变工作目录
    isClose: 是否关闭标准输入/输出/错误流
    */
    // 1、屏蔽可能引起程序异常退出的信号
    signal(SIGCHLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);

    // 2、避免进程组组长
    if (fork() > 0)
        exit(0);
    
    // 3、设置让自己成为一个新的会话
    setsid();

    // 4、改变工作目录
    if(isChdir)
    {
        chdir(defaultDir);
    }

    // 5、关闭文件描述符
    if(isClose)
    {
        ::close(0);
        ::close(1);
        ::close(2);
    }
    else
    {
        int fd = open(dev_null, O_RDWR);
        if(fd > 0)
        {
            dup2(fd, 0);
            dup2(fd, 1);
            dup2(fd, 2);
            ::close(fd);
        }
    }
}

